#!/usr/bin/python
# -*- coding: utf-8 -*-
# @author  : ganuoxun
# @description : 查询条件的model，结构参考mongodb的查询语句结构

from typing import List, Optional, Any
from pydantic import BaseModel, Field


class QueryDetail(BaseModel):
    field_name: str
    field_value: Any
    link: str
    oparation: str

    def get_operator(self) -> str:
        return ''.join(['$', self.oparation])


class SortDetail(BaseModel):
    field_name: str
    order: int


class QuerySchema(BaseModel):
    query: List[QueryDetail] = Field(...)
    projection: Optional[List[str]] = None
    sort: Optional[List[SortDetail]] = None
    limit: Optional[int] = Field(default=100, gt=0, lte=10000)
    skip: Optional[int] = Field(default=0, gte=0, lte=10000)

    def get_filter(self) -> dict:
        and_query = []
        or_query = []
        not_query = []
        nor_query = []

        if self.query:
            for query_detail in self.query:
                if query_detail.link == 'and':
                    and_query.append({query_detail.field_name: {query_detail.get_operator(): query_detail.field_value}})
                elif query_detail.link == 'or':
                    or_query.append({query_detail.field_name: {query_detail.get_operator(): query_detail.field_value}})
                elif query_detail.link == 'not':
                    not_query.append({query_detail.field_name: {query_detail.get_operator(): query_detail.field_value}})
                elif query_detail.link == 'nor':
                    nor_query.append({query_detail.field_name: {query_detail.get_operator(): query_detail.field_value}})

        query = {}
        if len(and_query) > 0:
            query['$and'] = and_query
        if len(or_query) > 0:
            query['$or'] = or_query
        if len(not_query) > 0:
            query['$not'] = not_query
        if len(nor_query) > 0:
            query['$nor'] = nor_query
        return query

    def get_projection(self) -> dict:
        projection_dict = {}
        if self.projection and len(self.projection) > 0:
            for field_name in self.projection:
                projection_dict[field_name] = 1
        return projection_dict

    def get_sort_by(self) -> dict:
        sort_by = {}
        if self.sort and len(self.sort) > 0:
            for sort_detail in self.sort:
                sort_by[sort_detail.field_name] = sort_detail.order
        return sort_by


class RunSparkSchema(BaseModel):
    bash_str: list
